#include "threadpool.h"
#include <bits/pthreadtypes.h>
#include <pthread.h>

int queueInit(task_queue_t *que)
{
    assert(que != NULL);//断言
    que->pFront = NULL;
    que->pRear = NULL;
    que->queueSize = 0;
    que->exitflag = 0;
    int ret = pthread_mutex_init(&que->mutex, NULL);
    THREAD_ERROR_CHECK(ret, "pthread_mutex_init");
    ret = pthread_cond_init(&que->cond, NULL);
    THREAD_ERROR_CHECK(ret, "pthread_cond_init");
    return 0;//成功返回值为0, 失败返回-1
}

int queueDestroy(task_queue_t * que)
{
    assert(que != NULL);
    int ret = pthread_mutex_destroy(&que->mutex);
    THREAD_ERROR_CHECK(ret, "pthread_mutex_destroy");
    ret = pthread_cond_destroy(&que->cond);
    THREAD_ERROR_CHECK(ret, "pthread_cond_destroy");
    return 0;
}

//生产者的角色：元素入队
int taskEnqueue(task_queue_t * que, int peerfd)
{
    assert(que != NULL);
    task_t * pNew = (task_t*)calloc(1, sizeof(task_t));
    pNew->peerfd = peerfd;

    pthread_mutex_lock(&que->mutex);
    if(queueEmpty(que)) {
        que->pFront = que->pRear = pNew;
    } else {
        que->pRear->pNext = pNew;
        que->pRear = pNew;
    }
    ++que->queueSize;
    pthread_cond_signal(&que->cond);//通知消费者取数据
    pthread_mutex_unlock(&que->mutex);
    return 0;
}

//消费者角色：元素出队
int  taskDequeue(task_queue_t * que)
{
    assert(que != NULL);
    pthread_mutex_lock(&que->mutex);
    //防止有 虚假唤醒  的情况，需要使用while
    while((!que->exitflag) && queueEmpty(que)) {
        pthread_cond_wait(&que->cond, &que->mutex);
    }
    int fd = -1;
    if(!que->exitflag) {
        task_t * pDelete = que->pFront;
        fd = pDelete->peerfd;
        if(taskSize(que) == 1) {
            que->pFront = que->pRear = NULL;
        } else {
            que->pFront = que->pFront->pNext;
        }
        que->queueSize--;
        free(pDelete);
    } 
    pthread_mutex_unlock(&que->mutex);
    return fd;
}

int taskSize(task_queue_t * que)
{
    return que->queueSize; 
}

int queueEmpty(task_queue_t * que)//1表示为空，0表示不为空
{
    return que->queueSize == 0;
}

void wakeup(task_queue_t * que)
{
    que->exitflag = 1;
    pthread_cond_broadcast(&que->cond);
}

int queueEmptyWithlock(task_queue_t * que)
{
    pthread_mutex_lock(&que->mutex);
    int flag = (que->queueSize == 0);
    pthread_mutex_unlock(&que->mutex);
    return flag;
}
